package environment
{
    import away3d.containers.ObjectContainer3D;
    import away3d.lights.DirectionalLight;
    import away3d.lights.PointLight;
    import away3d.materials.ColorMaterial;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.GradientType;
    import flash.display.Shape;
    import flash.filters.BlurFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.geom.Vector3D;
    import flash.utils.Endian;
    
    import objects.BitmapPlane;
    import objects.ColorPlane;

    public class Environment
    {
        public static var MIN_RADIUS : Number = 5;
        public static var MAX_RADIUS : Number = 50;
        public static var SIZE_MULTIPLIER : Number = 20;
        public static var BORDER : Number = 2.0;
        public static var NO_MANS_WIDTH : Number = 2.0;
        
        public var width : int = 32;
        public var height: int = 32;
        
        public var worldWidth : int = 32;
        public var worldHeight: int = 32;
        
        public var toxicLayer : EnvironmentLayer;
        public var nutrientLayer : EnvironmentLayer;
        public var fluidityLayer : EnvironmentLayer;
        
        public var parentContainer : ObjectContainer3D;
        
        public var verts : Array = [];
        
        public function Environment(parentContainer :ObjectContainer3D, width, height) : void
        {
            this.width = width;
            this.height = height;
            this.worldWidth = width * SIZE_MULTIPLIER;
            this.worldHeight = height * SIZE_MULTIPLIER;
            
            var light : DirectionalLight = new DirectionalLight();
            light.direction = new Vector3D(0,0, 1);
            light.color = 0xffffff;
            
            parentContainer.addChild(light);
            
            var cmat : ColorMaterial = new ColorMaterial(0xFFFFFF, 0.5);
            cmat.lights = [light];
            
            this.parentContainer = parentContainer;
            
            toxicLayer = new EnvironmentLayer(EnvVert.TOXIC, this, cmat, 16, 0, toxicHeightMap);
            nutrientLayer = new EnvironmentLayer(EnvVert.NUTRIENT, this, cmat, 8, 0, nutrientHeightMap);
            fluidityLayer = new EnvironmentLayer(EnvVert.FLUID, this, cmat, 0, 0, fluidityHeightMap);
            
            // Initialize our vertexes
            for (var x : int = 0; x < width; x++)
            {
                verts[x] = [];
                
                for (var y : int = 0; y < width; y++)
                {
                    verts[x][y] = new EnvVert(x, y);
                    verts[x][y].layers[EnvVert.TOXIC] = toxicLayer;
                    verts[x][y].layers[EnvVert.NUTRIENT] = nutrientLayer;
                    verts[x][y].layers[EnvVert.FLUID] = fluidityLayer;
                }
            }
        }

        public function subtractNutrients(x : Number, y : Number, radius : Number, amount : Number) : void
        {
            /*var shape : Shape = new Shape();

            var mat : Matrix = new Matrix();

            mat.createGradientBox(radius * 2, radius * 2, 0, 0, 0);

            shape.graphics.beginGradientFill(GradientType.RADIAL, [uint(255 * amount) << 8, 0], [100, 0], [0, 0xAA], mat);
            shape.graphics.drawEllipse(0, 0, radius * 2, radius * 2);
            shape.graphics.endFill();

            var mat2 : Matrix = new Matrix();
            mat2.tx = x - radius;
            mat2.ty = y - radius;

            bdNutrients.draw(shape, mat2, null, BlendMode.SUBTRACT);*/
        }

        public function subtractToxins(x : Number, y : Number, radius : Number, amount : Number) : void
        {
            /*var shape : Shape = new Shape();

            var mat : Matrix = new Matrix();

            mat.createGradientBox(radius * 2, radius * 2, 0, 0, 0);

            shape.graphics.beginGradientFill(GradientType.RADIAL, [uint(255 * amount) << 16, 0], [100, 0], [0, 0xAA], mat);
            shape.graphics.drawEllipse(0, 0, radius * 2, radius * 2);
            shape.graphics.endFill();

            var mat2 : Matrix = new Matrix();
            mat2.tx = x - radius;
            mat2.ty = y - radius;

            bdToxic.draw(shape, mat2, null, BlendMode.SUBTRACT);*/
        }

        public function generateEnvironment(toxicCells : Number, nutrientCells : Number, fluidCells : Number, toxicBase : uint = 0x0, nutrientBase : uint = 0x0, fluidBase : uint = 0x40) : void
        {
            toxicLayer.generateRandom(toxicCells, width / 20, width / 2, 0.3, 1.0, 3, 1);
            nutrientLayer.generateRandom(nutrientCells, width / 20, width / 2, 0.3, 1.0, 3, 1);
            fluidityLayer.generateRandom(fluidCells, width / 20, width / 2, 0.3, 1.0, 3, 1);
        }
        
        private function toxicHeightMap(x : int, y : int, pixel : uint) : Number
        {
            return (((pixel >> 16) & 0xFF) / 255) * 100;
        }

        private function nutrientHeightMap(x : int, y : int, pixel : uint) : Number
        {
            return -(((pixel >> 8) & 0xFF) / 255) * 100;
        }

        private function fluidityHeightMap(x : int, y : int, pixel : uint) : Number
        {
            return 0;
        }
        
        /**
         * This method returns the four vertexes on the 2D plane to the provided x and y values.
         */
        public function getFourNearestVerts(x : Number, y : Number) : Array
        {
            //x /= SIZE_MULTIPLIER;
            //y /= SIZE_MULTIPLIER;

            var v1 : EnvVert = verts[Math.floor(x)][Math.floor(y)];
            var v2 : EnvVert = verts[Math.ceil(x)][Math.floor(y)];
            var v3 : EnvVert = verts[Math.ceil(x)][Math.ceil(y)];
            var v4 : EnvVert = verts[Math.floor(x)][Math.ceil(y)];

            return [v1,v2,v3,v4];
        }
        
        public function getVirtualVertValue(x : Number, y : Number) : EnvVertVirtual
        {
            var verts : Array = getFourNearestVerts(x, y);
            
            //x /= SIZE_MULTIPLIER;
            //y /= SIZE_MULTIPLIER;
            
            var distances : Array = [0, 0, 0, 0];
            
            var i : int = 0;
            var avgs : Array = [0,0,0];
            var closest : int= -1;
            var closestDistance : Number = 1000;
            
            for each (var vert : EnvVert in verts)
            {
                distances[i] = Math.sqrt((verts[i].x - x) * (verts[i].x - x) + (verts[i].y - y) * (verts[i].y - y));
                
                for (var layer : int = 0; layer < 3; layer++)
                {
                    avgs[layer] += (verts[i] as EnvVert).getVertColor(layer, layer) * (1.41421356 - distances[i]);
                }
            
                if (distances[i] < closestDistance)
                {
                    closestDistance = distances[i];
                    closest = i;
                }
                
                i++;
            }
            
            for (var j : int = 0; j < 3; j++)
            {
                avgs[j] /= 4;
            }
            
            var vv : EnvVertVirtual = new EnvVertVirtual();
            
            vv.closestEnvVert = verts[closest] as EnvVert;
            
            vv.colorValues = avgs;
            
            return vv;
        }
    }
}